package cn.openea.perpartner.meily.web.controller;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.openea.perpartner.common.core.service.db.MyBatisBatchSaveAndFlush;
import cn.openea.perpartner.common.core.utils.RegexUtil;
import cn.openea.perpartner.common.core.utils.SpringContextUtils;
import cn.openea.perpartner.common.core.utils.poi.ExcelUtil;
import cn.openea.perpartner.common.core.web.domain.AjaxResult;
import cn.openea.perpartner.meily.constant.enums.ExpressCompany;
import cn.openea.perpartner.meily.constant.enums.ExpressStatus;
import cn.openea.perpartner.meily.eventlistener.event.SyncLogisticsEvent;
import cn.openea.perpartner.meily.thirdparty.ExpressServiceApi;
import cn.openea.perpartner.meily.util.UserContext;
import cn.openea.perpartner.meily.web.entity.*;
import cn.openea.perpartner.meily.web.entity.dto.*;
import cn.openea.perpartner.meily.web.entity.vo.OrderRecordVo;
import cn.openea.perpartner.meily.web.entity.vo.ProvideSamplesSubVo;
import cn.openea.perpartner.meily.web.entity.vo.SysUserSearchVo;
import cn.openea.perpartner.meily.web.mapper.CustomerMapper;
import cn.openea.perpartner.meily.web.mapper.ProviderMapper;
import cn.openea.perpartner.meily.web.service.*;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ysk
 * @version 1.0.1
 * @Description 用来项目中数据的问题，只提供给开发人员调用
 * @createTime 2023年05月09日 17:31:00
 */
@Slf4j
@Api(tags = "开发接口")
@RestController
@RequestMapping("/open")
public class OpenController {


    @Resource
    private ISysUserService sysUserService;
    @Resource
    private IProviderService providerService;
    @Resource
    private IPersonalInfoService personalInfoService;
    @Resource
    private MyBatisBatchSaveAndFlush batchSaveAndFlush;
    @Resource
    private IGroupBuyingSubService groupBuyingSubService;
    @Resource
    private ExpressServiceApi expressServiceApi;
    @Resource
    private IProvideSamplesSubService provideSamplesSubService;
    @Resource
    private IGoodsSupplyChainService goodsSupplyChainService;
    @Resource
    private ICourseCategoryService courseCategoryService;

    @ApiOperation("个人信息表数据同步")
    @PostMapping("/customer/data/sync")
    public AjaxResult customerDataSync() {
        SysUserSearchVo searchVo = new SysUserSearchVo();
        searchVo.setFilterUsers(false);
        // 拿到全部用户数据
        List<UserDetailDTO> userDetailDTOList = sysUserService.findList(searchVo);
        // 拿到区域服务商数据
        Map<String, Provider> providerMap = providerService.selectList(null)
                .stream()
                .collect(Collectors.toMap(
                        item -> Optional.ofNullable(item.getUserId()).orElse("-1"),
                        item -> Optional.of(item).orElse(null),
                        (v1, v2) -> v1 = v2));
        // 拿到测评师数据
        Map<String, PersonalInfo> personalInfoMap = personalInfoService.getPersonalInfoList(new SearchDto())
                .stream()
                .collect(Collectors.toMap(
                        item -> Optional.ofNullable(item.getUserId()).orElse("-1"),
                        item -> Optional.of(item).orElse(null),
                        (v1, v2) -> v1 = v2));
        // 构建需要同步的数据
        List<Customer> customerList = userDetailDTOList.parallelStream()
                .filter((item) -> RegexUtil.match("^\\d+$", item.getUserId()))
                .map(item -> {
                    Customer customer = Customer.builder()
                            .userId(item.getUserId())
                            .userName(item.getNickName())
                            .realName(item.getRealName())
                            .avatarUrl(item.getAvatar())
                            .sex(item.getSex())
                            .ageGroup(item.getAgeGroup())
                            .identityJob(item.getIdentityJob())
                            .monthlyIncome(item.getMonthlyIncome())
                            .phoneNumber(item.getPhone())
                            .region(item.getRegion())
                            .streetVillage(item.getStreetVillage())
                            .address(item.getAddress())
                            .openid(item.getOpenid())
                            .unionid(item.getUnionid())
                            .isSubscribed(StringUtils.isBlank(item.getSubscribedWx()) ? 0 : Integer.parseInt(item.getSubscribedWx()))
                            .providerId(providerMap.get(item.getUserId()) != null ? String.valueOf(providerMap.get(item.getUserId()).getId()) : null)
                            .evaluatorId(personalInfoMap.get(item.getUserId()) != null ? personalInfoMap.get(item.getUserId()).getId() : null)
                            .build();
                    customer.setCreateTime(item.getCreateTime());
                    return customer;
                }).collect(Collectors.toList());
        // 导入数据，使用批处理
        batchSaveAndFlush.batchUpdateOrInsert(customerList, CustomerMapper.class, (item, mapper) -> mapper.insert(item));
        return AjaxResult.success();
    }

    @ApiOperation("处理物流信息同步")
    @PostMapping("/logistic/data/sync")
    public AjaxResult logisticDataSync() {
        // 处理订单数据同步
        OrderRecordVo recordVo = new OrderRecordVo();
        List<GroupBuyingSub> groupBuyingSubs = groupBuyingSubService.selectList(recordVo);
        Map<String, String> map = new HashMap<>();
        for (GroupBuyingSub detailsDto : groupBuyingSubs) {
            LogisticsDTOFactory.LogisticsRealTimeDTO realTimeDTO = null;
            if ("已发货".equals(detailsDto.getOrderStatus())) {
                // 去查实时物流更新
                String address = detailsDto.getAddress();
                JSONObject addressObj = new JSONObject();
                if (StrUtil.isNotBlank(address)) {
                    addressObj = JSONObject.parseObject(address);
                }
                String phone = "";
                if (!addressObj.isEmpty()) {
                    phone = addressObj.getString("PhoneNum");
                }
                ExpressCompany expressCompany = ExpressCompany.getByCode(detailsDto.getExpressCompanyCode());
                try {
                    realTimeDTO = expressServiceApi.realTimeLogistics(expressCompany, detailsDto.getCourierNumber(), phone);
                } catch (Exception e) {
                    map.put(detailsDto.getId(), "订单物流同步失败，失败原因" + e.getMessage());
                }
            }
            if ("已完成".equals(detailsDto.getOrderStatus()) || "已退款".equals(detailsDto.getOrderStatus())) {
                // 不去同步，直接默认为已经存在
                realTimeDTO = new LogisticsDTOFactory.LogisticsRealTimeDTO();
                realTimeDTO.setCom(detailsDto.getExpressCompanyCode());
                realTimeDTO.setState(ExpressStatus.SIGN.getStatus());
            }
            // 数据量较小 直接同步，不批量操作
            // 保存使用监听的方式 需要同步
            if (realTimeDTO != null) {
                try {
                    SpringContextUtils.getApplicationContext().publishEvent(new SyncLogisticsEvent(this, detailsDto, realTimeDTO, null));
                } catch (Exception e) {
                    map.put(detailsDto.getId(), "订单物流同步失败，失败原因" + e.getMessage());
                }
            }
        }
        // 处理样品数据
        List<ProvideSamplesSub> samplesSubs = provideSamplesSubService.getListByVo(new ProvideSamplesSubVo());
        for (ProvideSamplesSub samplesSub : samplesSubs) {
            LogisticsDTOFactory.LogisticsRealTimeDTO realTimeDTO = null;
            if ("已发货".equals(samplesSub.getOrderStatus())) {
                ExpressCompany expressCompany = ExpressCompany.getByCode(samplesSub.getExpressCompanyCode());
                try {
                    realTimeDTO = expressServiceApi.realTimeLogistics(expressCompany, samplesSub.getCourierNumber(), samplesSub.getConsigneePhoneNum());
                } catch (Exception e) {
                    map.put(samplesSub.getId(), "样品物流同步失败，失败原因" + e.getMessage());
                }
            }
            if ("已完成".equals(samplesSub.getOrderStatus())) {
                realTimeDTO = new LogisticsDTOFactory.LogisticsRealTimeDTO();
                realTimeDTO.setCom(samplesSub.getExpressCompanyCode());
                realTimeDTO.setState(ExpressStatus.SIGN.getStatus());
            }
            if (realTimeDTO != null) {
                try {
                    SpringContextUtils.getApplicationContext().publishEvent(new SyncLogisticsEvent(this, samplesSub, realTimeDTO, null));
                } catch (Exception e) {
                    map.put(samplesSub.getId(), "订单物流同步失败，失败原因" + e.getMessage());
                }
            }

        }
        return AjaxResult.success(map);
    }

    @ApiOperation("初始化供应链数据")
    @PostMapping("/goods/supply/chain/init")
    public AjaxResult initGoodsSupplyChain(MultipartFile file) {
        ExcelUtil<GoodsSupplyChainDTOFactory.ImportExportDTO> util = new ExcelUtil<>(GoodsSupplyChainDTOFactory.ImportExportDTO.class);
        List<GoodsSupplyChainDTOFactory.ImportExportDTO> importExcel = null;
        try {
            importExcel = util.importExcel(file.getInputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<String> dataList = new ArrayList<>();
        for (GoodsSupplyChainDTOFactory.ImportExportDTO category : importExcel) {
            dataList.add(category.getCategory() + "#" + category.getClassify() + "#" + category.getName());
        }
        List<GoodsSupplyChain> allLis = new ArrayList<>();
        HashMap<String, Long> categoryMap = new HashMap<>();
        for (String data : dataList) {
            String[] arr = data.split("#");
            categoryMap.put(arr[0], 0L);
        }
        List<GoodsSupplyChain> categoryList = new ArrayList<>();
        Snowflake snowflake = IdUtil.createSnowflake(1, 3);
        categoryMap.forEach((key, value) -> {
            GoodsSupplyChain goodsSupplyChain = new GoodsSupplyChain();
            goodsSupplyChain.setName(key);
            goodsSupplyChain.setId(snowflake.nextId());
            goodsSupplyChain.setParentId(value);
            goodsSupplyChain.setUpdateUser(UserContext.getUserId());
            goodsSupplyChain.setCreateUser(UserContext.getUserId());
            categoryList.add(goodsSupplyChain);
        });
        List<GoodsSupplyChain> classifyList = new ArrayList<>();
        for (String data : dataList) {
            String[] arr = data.split("#");
            for (GoodsSupplyChain goodsSupplyChain : categoryList) {
                if (arr[0].equals(goodsSupplyChain.getName())) {
                    boolean isExist = false;
                    for (GoodsSupplyChain classify : classifyList) {
                        if (classify.getName().equals(arr[1])
                                && classify.getParentId().equals(goodsSupplyChain.getId())) {
                            isExist = true;
                            break;
                        }
                    }
                    if (isExist) {
                        break;
                    }
                    GoodsSupplyChain classify = new GoodsSupplyChain();
                    classify.setName(arr[1]);
                    classify.setId(snowflake.nextId());
                    classify.setParentId(goodsSupplyChain.getId());
                    classify.setUpdateUser(UserContext.getUserId());
                    classify.setCreateUser(UserContext.getUserId());
                    classifyList.add(classify);
                }
            }
        }
        List<GoodsSupplyChain> pecificList = new ArrayList<>();
        for (String data : dataList) {
            String[] arr = data.split("#");
            for (GoodsSupplyChain category : categoryList) {
                for (GoodsSupplyChain classify : classifyList) {
                    if (arr[0].equals(category.getName()) && arr[1].equals(classify.getName())
                            && category.getId().equals(classify.getParentId())
                    ) {
                        GoodsSupplyChain pecific = new GoodsSupplyChain();
                        pecific.setName(arr[2]);
                        pecific.setParentId(classify.getId());
                        pecific.setId(snowflake.nextId());
                        pecific.setCreateUser(UserContext.getUserId());
                        pecific.setUpdateUser(UserContext.getUserId());
                        pecificList.add(pecific);
                    }
                }

            }
        }
        allLis.addAll(categoryList);
        allLis.addAll(classifyList);
        allLis.addAll(pecificList);
        goodsSupplyChainService.saveBatch(allLis);
        return AjaxResult.success();
    }

    @ApiOperation("补全区域服务商类型")
    @PostMapping("/complements/provider/type")
    public AjaxResult complementsProviderType(MultipartFile file) {
        ExcelUtil<ProviderDTOFactory.ExportDTO> util = new ExcelUtil<>(ProviderDTOFactory.ExportDTO.class);
        try {
            List<ProviderDTOFactory.ExportDTO> exportDTOList = util.importExcel(file.getInputStream());
            exportDTOList = exportDTOList.parallelStream()
                    // 过滤掉区域服务商编号为空的数据
                    .filter(item -> StringUtils.isNotBlank(item.getProviderId()))
                    .collect(Collectors.toList());
            batchSaveAndFlush.batchUpdateOrInsert(exportDTOList, ProviderMapper.class, (item, mapper) -> mapper.complementsStoreType(item.getProviderId(), item.getStoreType()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success();
    }

    @ApiOperation("初始化课程分类")
    @PostMapping("/course/category/init")
    public AjaxResult initCourseCategory(MultipartFile file) {
        ExcelUtil<GoodsSupplyChainDTOFactory.ImportExportDTO> util = new ExcelUtil<>(GoodsSupplyChainDTOFactory.ImportExportDTO.class);
        List<GoodsSupplyChainDTOFactory.ImportExportDTO> importExcel = null;
        try {
            importExcel = util.importExcel(file.getInputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<String> dataList = new ArrayList<>();
        for (GoodsSupplyChainDTOFactory.ImportExportDTO category : importExcel) {
            dataList.add(category.getCategory() + "#" + category.getClassify());
        }
        List<CourseCategory> allLis = new ArrayList<>();
        HashMap<String, Long> categoryMap = new HashMap<>();
        for (String data : dataList) {
            String[] arr = data.split("#");
            categoryMap.put(arr[0], 0L);
        }
        List<CourseCategory> courseCategories = new ArrayList<>();
        Snowflake snowflake = IdUtil.createSnowflake(1, 3);
        categoryMap.forEach((key, value) -> {
            CourseCategory courseCategory = new CourseCategory();
            courseCategory.setName(key);
            courseCategory.setId(snowflake.nextId());
            courseCategory.setParentId(value);
            courseCategories.add(courseCategory);
        });
        List<CourseCategory> classifyList = new ArrayList<>();
        for (String data : dataList) {
            String[] arr = data.split("#");
            for (CourseCategory goodsSupplyChain : courseCategories) {
                if (arr[0].equals(goodsSupplyChain.getName())) {
                    boolean isExist = false;
                    for (CourseCategory classify : classifyList) {
                        if (classify.getName().equals(arr[1])
                                && classify.getParentId().equals(goodsSupplyChain.getId())) {
                            isExist = true;
                            break;
                        }
                    }
                    if (isExist) {
                        break;
                    }
                    CourseCategory classify = new CourseCategory();
                    classify.setName(arr[1]);
                    classify.setId(snowflake.nextId());
                    classify.setParentId(goodsSupplyChain.getId());
                    classifyList.add(classify);
                }
            }
        }
        allLis.addAll(courseCategories);
        allLis.addAll(classifyList);
        courseCategoryService.saveBatch(allLis);
        return AjaxResult.success();
    }
}
